#include <stdio.h>
#include <stdlib.h> 
#include <time.h>
#include <string.h>

#define MAXDEPTH 3
#define EDGEFILE   "edgeTable.txt"
#define CORNERFILE "cornerTable.txt"
#define MAXQUEUE 5000

#define C1 0
#define C2 1
#define C3 2
#define C4 3
#define C5 4
#define C6 5
#define C7 6
#define C8 7
#define E9 8
#define E10 9
#define E11 10
#define E12 11
#define E13 12
#define E14 13
#define E15 14
#define E16 15
#define E17 16
#define E18 17
#define E19 18
#define E20 19


#define PASSEDGES theCube[E9].w, theCube[E9].o, theCube[E10].w, theCube[E10].b, theCube[E11].r, theCube[E11].w, theCube[E12].w, theCube[E12].g, theCube[E13].b, theCube[E13].y, theCube[E14].y, theCube[E14].o, theCube[E15].y, theCube[E15].g, theCube[E16].r, theCube[E16].y, theCube[E17].r, theCube[E17].g, theCube[E18].r, theCube[E18].b, theCube[E19].b, theCube[E19].o, theCube[E20].o, theCube[E20].g

#define PASSCORNERS theCube[C1].w, theCube[C1].o, theCube[C1].g, theCube[C2].w, theCube[C2].b, theCube[C2].o, theCube[C3].r, theCube[C3].w, theCube[C3].g, theCube[C4].r, theCube[C4].w, theCube[C4].b, theCube[C5].r, theCube[C5].b, theCube[C5].y, theCube[C6].b, theCube[C6].o, theCube[C6].y, theCube[C7].r, theCube[C7].y, theCube[C7].g, theCube[C8].o, theCube[C8].y, theCube[C8].g



/*******************************************************************/
/************************** Declarations ***************************/
/*******************************************************************/

struct aCube {
  char r;
  char w;
  char b;
  char o;
  char y;
  char g;
};

void allRotations();
void resetCube( struct aCube *);
void copyCube( struct aCube *, struct aCube *);
void scramble( struct aCube *, short);
void printStepCube( struct aCube *);
void printCrossCube( struct aCube *);
void saveEdgeCubie( struct aCube *, FILE*, short);
void saveCornerCubie( struct aCube *, FILE*, short);
void setCornersFromString( struct aCube *, char []);
void setEdgesFromString(   struct aCube *, char []);
void setCubeFromStrings( struct aCube *, char [], char[]);
void setCubeFromString(struct aCube *, char []);

void setEdges( struct aCube *,//
       char, char, char, char, char, char, char, char,//
       char, char, char, char, char, char, char, char,//
       char, char, char, char, char, char, char, char);
void setCorners( struct aCube *,//
       char, char, char, char, char, char, char, char,//
       char, char, char, char, char, char, char, char,//
       char, char, char, char, char, char, char, char);
short getEdgeHeuristic( struct aCube *, FILE*);
short getCornerHeuristic( struct aCube *, FILE*);
short getHeuristic( struct aCube *);

void popQueue(struct aCube *, struct aCube **, int*);
void addQueue( struct aCube *, struct aCube **, char, int, int*, short);
int checkEdgeDuplicates( struct aCube *, short);
int checkCornerDuplicates( struct aCube *, short);
void generateTables( struct aCube **, int*, int*, short);

void generateEdges( struct aCube *, FILE*, short,//
       char, char, char, char, char, char, char, char,//
       char, char, char, char, char, char, char, char,//
       char, char, char, char, char, char, char, char);

void generateCorners( struct aCube *, FILE*, short,//
       char, char, char, char, char, char, char, char,//
       char, char, char, char, char, char, char, char,//
       char, char, char, char, char, char, char, char);

/*Moves denoted in number of clockwise rotations*/

int rotate( struct aCube *, char, int);

void r1c( struct aCube *);
void r1e( struct aCube *);
void r2c( struct aCube *);
void r2e( struct aCube *);
void r3c( struct aCube *);
void r3e( struct aCube *);

void w1c( struct aCube *);
void w1e( struct aCube *);
void w2c( struct aCube *);
void w2e( struct aCube *);
void w3c( struct aCube *);
void w3e( struct aCube *);

void b1c( struct aCube *);
void b1e( struct aCube *);
void b2c( struct aCube *);
void b2e( struct aCube *);
void b3c( struct aCube *);
void b3e( struct aCube *);

void o1c( struct aCube *);
void o1e( struct aCube *);
void o2c( struct aCube *);
void o2e( struct aCube *);
void o3c( struct aCube *);
void o3e( struct aCube *);

void y1c( struct aCube *);
void y1e( struct aCube *);
void y2c( struct aCube *);
void y2e( struct aCube *);
void y3c( struct aCube *);
void y3e( struct aCube *);

void g1c( struct aCube *);
void g1e( struct aCube *);
void g2c( struct aCube *);
void g2e( struct aCube *);
void g3c( struct aCube *);
void g3e( struct aCube *);


/******************************************************************/
/************************ Main Function ***************************/
/******************************************************************/

int main() {
  int *frontQ;
  frontQ = 0;
  int *rearQ;
  rearQ = 0;
  short currentDepth = 0;
  struct aCube mainCube[20] = {
    { 'Z', 'W', 'Z', 'O', 'Z', 'G'},
    { 'Z', 'W', 'B', 'O', 'Z', 'Z'},
    { 'R', 'W', 'Z', 'Z', 'Z', 'G'},
    { 'R', 'W', 'B', 'Z', 'Z', 'Z'},
    { 'R', 'Z', 'B', 'Z', 'Y', 'Z'},
    { 'Z', 'Z', 'B', 'O', 'Y', 'Z'},
    { 'R', 'Z', 'Z', 'Z', 'Y', 'G'},
    { 'Z', 'Z', 'Z', 'O', 'Y', 'G'},
    { 'Z', 'W', 'Z', 'O', 'Z', 'Z'},
    { 'Z', 'W', 'B', 'Z', 'Z', 'Z'},
    { 'R', 'W', 'Z', 'Z', 'Z', 'Z'},
    { 'Z', 'W', 'Z', 'Z', 'Z', 'G'},
    { 'Z', 'Z', 'B', 'Z', 'Y', 'Z'},
    { 'Z', 'Z', 'Z', 'O', 'Y', 'Z'},
    { 'Z', 'Z', 'Z', 'Z', 'Y', 'G'},
    { 'R', 'Z', 'Z', 'Z', 'Y', 'Z'},
    { 'R', 'Z', 'Z', 'Z', 'Z', 'G'},
    { 'R', 'Z', 'B', 'Z', 'Z', 'Z'},
    { 'Z', 'Z', 'B', 'O', 'Z', 'Z'},
    { 'Z', 'Z', 'Z', 'O', 'Z', 'G'}
  };

  struct aCube theQueue[MAXQUEUE][20];
  void *ptrQueue = theQueue[0][0]
  copyCube( theQueue[0][0], mainCube);
  generateTables( &ptrQueue, frontQ, rearQ, currentDepth);
  printCrossCube( mainCube);

  return 0;
}

/*******************************************************************/
/********************** Function Definitions ***********************/
/*******************************************************************/

void generateTables( struct aCube ** theQueue, int* frontQ, int* rearQ, short currentDepth) {
  if( MAXDEPTH == currentDepth ) return;
  else{
    struct aCube theCube[20];
    popQueue( theCube, theQueue, frontQ);
    char face[6] = { 'r', 'w', 'b', 'o', 'y', 'g' };
    int i, j;
    for( i=0; i<=5; i++) {
      for( j=1; j<=3; j++) {
        addQueue( theCube, theQueue, face[i], j, rearQ, currentDepth);
      }
    }
    generateTables( theQueue, frontQ, rearQ, currentDepth+1);
  }
}

void addQueue( struct aCube * theCube, struct aCube ** theQueue, char c, int i, int* rearQ, short currentDepth) {
  struct aCube localCube[20];
  copyCube( localCube, theCube);
  rotate( localCube, c, i);
  checkEdgeDuplicates( localCube, currentDepth);
  checkCornerDuplicates( localCube, currentDepth);
  void *ptrQueueRear = theQueue[rearQ][0];
  copyCube( &ptrQueueRear, localCube);
  rearQ++;
}


void popQueue( struct aCube * theCube, struct aCube ** theQueue, int* frontQ) {
  void *ptrQueueFront = theQueue[frontQ][0];
  copyCube( theCube, &ptrQueueFront);
  frontQ++;
}


int checkEdgeDuplicates( struct aCube * theCube, short currentDepth) {
  char cube[24];
  int distToGoal;
  FILE* edgeFile;
  long linePosition;
  edgeFile = fopen( EDGEFILE, "r");
  while (fscanf( edgeFile, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%d\n",
                 &cube[0],  &cube[1],  &cube[2],  &cube[3],  &cube[4],
                 &cube[5],  &cube[6],  &cube[7],  &cube[8],  &cube[9],
                 &cube[10], &cube[11], &cube[12], &cube[13], &cube[14],
                 &cube[15], &cube[16], &cube[17], &cube[18], &cube[19],
                 &cube[20], &cube[21], &cube[22], &cube[23], &distToGoal) != EOF) {
    if (theCube[E9].w  == cube[0]){
      if (theCube[E9].o  == cube[1]){
        if (theCube[E10].w == cube[2]){
          if (theCube[E10].b == cube[3]){
            if (theCube[E11].r == cube[4]){
              if (theCube[E11].w == cube[5]){
                if (theCube[E12].w == cube[6]){
                  if (theCube[E12].g == cube[7]){
                    if (theCube[E13].b == cube[8]){
                      if (theCube[E13].y == cube[9]){
                        if (theCube[E14].y == cube[10]){
                          if (theCube[E14].o == cube[11]){
                            if (theCube[E15].y == cube[12]){
                              if (theCube[E15].g == cube[13]){
                                if (theCube[E16].r == cube[14]){
                                  if (theCube[E16].y == cube[15]){
                                    if (theCube[E17].r == cube[16]){
                                      if (theCube[E17].g == cube[17]){
                                        if (theCube[E18].r == cube[18]){
                                          if (theCube[E18].b == cube[19]){
                                            if (theCube[E19].b == cube[20]){
                                              if (theCube[E19].o == cube[21]){
                                                if (theCube[E20].o == cube[22]){
                                                  if (theCube[E20].g == cube[23]){
  						    if (currentDepth >= distToGoal){
						      fclose(edgeFile);
						      return 0;
						      }}}}}}}}}}}}}}}}}}}}}}}}}
  }
  fclose(edgeFile);
  edgeFile = fopen( EDGEFILE, "a");
  fseek(edgeFile, 0, SEEK_END);
  saveEdgeCubie( theCube, edgeFile, currentDepth);
  fclose(edgeFile);
  return 1;
}


int checkCornerDuplicates( struct aCube * theCube, short currentDepth) {
  char cube[24];
  int distToGoal;
  FILE* cornerFile;
  long linePosition;
  cornerFile = fopen( CORNERFILE, "r");
  while (fscanf( cornerFile, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%d\n",//
                 &cube[0],  &cube[1],  &cube[2],  &cube[3],  &cube[4],//
                 &cube[5],  &cube[6],  &cube[7],  &cube[8],  &cube[9],//
                 &cube[10], &cube[11], &cube[12], &cube[13], &cube[14],//
                 &cube[15], &cube[16], &cube[17], &cube[18], &cube[19],//
                 &cube[20], &cube[21], &cube[22], &cube[23], &distToGoal) != EOF) {

    if (theCube[C1].w == cube[0]){
      if (theCube[C1].o == cube[1]){
        if (theCube[C1].g == cube[2]){
          if (theCube[C2].w == cube[3]){
            if (theCube[C2].b == cube[4]){
              if (theCube[C2].o == cube[5]){
                if (theCube[C3].r == cube[6]){
                  if (theCube[C3].w == cube[7]){
                    if (theCube[C3].g == cube[8]){
                      if (theCube[C4].r == cube[9]){
                        if (theCube[C4].w == cube[10]){
                          if (theCube[C4].b == cube[11]){
                            if (theCube[C5].r == cube[12]){
                              if (theCube[C5].b == cube[13]){
                                if (theCube[C5].y == cube[14]){
                                  if (theCube[C6].b == cube[15]){
                                    if (theCube[C6].o == cube[16]){
                                      if (theCube[C6].y == cube[17]){
                                        if (theCube[C7].r == cube[18]){
                                          if (theCube[C7].y == cube[19]){
                                            if (theCube[C7].g == cube[20]){
                                              if (theCube[C8].o == cube[21]){
                                                if (theCube[C8].y == cube[22]){
                                                  if (theCube[C8].g == cube[23]){
						    if (currentDepth >= distToGoal){
                                                      fclose(cornerFile);
                                                      return 0;
                                                      }}}}}}}}}}}}}}}}}}}}}}}}}
  }
  fclose(cornerFile);
  cornerFile = fopen( CORNERFILE, "a");
  fseek(cornerFile, 0, SEEK_END);
  saveCornerCubie( theCube, cornerFile, currentDepth);
  fclose(cornerFile);
  return 1;
}


short getHeuristic( struct aCube * theCube) {
  short cornerHeuristic, edgeHeuristic;

  FILE* cornerFile;
  FILE* edgeFile;
  cornerFile = fopen( CORNERFILE,"r");
  edgeFile = fopen(   EDGEFILE  ,"r");

  edgeHeuristic   = getEdgeHeuristic(theCube, edgeFile);
  cornerHeuristic = getCornerHeuristic(theCube, cornerFile);

  fclose(cornerFile);
  fclose(edgeFile);

  if( edgeHeuristic == -1 || cornerHeuristic == -1)
    return -1;
  else{
    if (edgeHeuristic >= cornerHeuristic ) 
      return edgeHeuristic;
    else 
      return cornerHeuristic;
  }
}


short getEdgeHeuristic( struct aCube * theCube, FILE* edgeFile) {
  int distToGoal;
  char cube[24];
  while (fscanf( edgeFile, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%d\n",//
                 &cube[0],  &cube[1],  &cube[2],  &cube[3],  &cube[4],// 
                 &cube[5],  &cube[6],  &cube[7],  &cube[8],  &cube[9],//
                 &cube[10], &cube[11], &cube[12], &cube[13], &cube[14],//       
                 &cube[15], &cube[16], &cube[17], &cube[18], &cube[19],//       
                 &cube[20], &cube[21], &cube[22], &cube[23], &distToGoal) != EOF) {
    if (theCube[E9].w  == cube[0]){
      if (theCube[E9].o  == cube[1]){
	if (theCube[E10].w == cube[2]){
	  if (theCube[E10].b == cube[3]){
	    if (theCube[E11].r == cube[4]){
	      if (theCube[E11].w == cube[5]){
		if (theCube[E12].w == cube[6]){
		  if (theCube[E12].g == cube[7]){
		    if (theCube[E13].b == cube[8]){
		      if (theCube[E13].y == cube[9]){
			if (theCube[E14].y == cube[10]){
			  if (theCube[E14].o == cube[11]){
			    if (theCube[E15].y == cube[12]){
			      if (theCube[E15].g == cube[13]){
				if (theCube[E16].r == cube[14]){
				  if (theCube[E16].y == cube[15]){
				    if (theCube[E17].r == cube[16]){
				      if (theCube[E17].g == cube[17]){
					if (theCube[E18].r == cube[18]){
					  if (theCube[E18].b == cube[19]){
					    if (theCube[E19].b == cube[20]){
					      if (theCube[E19].o == cube[21]){
						if (theCube[E20].o == cube[22]){
						  if (theCube[E20].g == cube[23]){
						    return distToGoal;
                                                    }}}}}}}}}}}}}}}}}}}}}}}}
  }
  return -1;
}


short getCornerHeuristic( struct aCube * theCube, FILE* filename) {
  short distToGoal;
  char cube[24];
  while (fscanf( filename, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%d\n",// 
		 &cube[0],  &cube[1],  &cube[2],  &cube[3],  &cube[4],//                 
		 &cube[5],  &cube[6],  &cube[7],  &cube[8],  &cube[9],//                  
		 &cube[10], &cube[11], &cube[12], &cube[13], &cube[14],//      
		 &cube[15], &cube[16], &cube[17], &cube[18], &cube[19],//     
		 &cube[20], &cube[21], &cube[22], &cube[23], &distToGoal) != EOF) {

    if (theCube[C1].w == cube[0]){
      if (theCube[C1].o == cube[1]){
        if (theCube[C1].g == cube[2]){
          if (theCube[C2].w == cube[3]){
            if (theCube[C2].b == cube[4]){
              if (theCube[C2].o == cube[5]){
                if (theCube[C3].r == cube[6]){
                  if (theCube[C3].w == cube[7]){
                    if (theCube[C3].g == cube[8]){
                      if (theCube[C4].r == cube[9]){
                        if (theCube[C4].w == cube[10]){
                          if (theCube[C4].b == cube[11]){
                            if (theCube[C5].r == cube[12]){
                              if (theCube[C5].b == cube[13]){
                                if (theCube[C5].y == cube[14]){
                                  if (theCube[C6].b == cube[15]){
                                    if (theCube[C6].o == cube[16]){
                                      if (theCube[C6].y == cube[17]){
                                        if (theCube[C7].r == cube[18]){
                                          if (theCube[C7].y == cube[19]){
                                            if (theCube[C7].g == cube[20]){
                                              if (theCube[C8].o == cube[21]){
                                                if (theCube[C8].y == cube[22]){
                                                  if (theCube[C8].g == cube[23]){
                                                    return distToGoal;
                                                    }}}}}}}}}}}}}}}}}}}}}}}}
  }
  return -1;
}



void setCornersFromString(struct aCube * theCube, char corners[]){
  if( strlen(corners) != 24 ){
    printf("Please enter an array with 24 consecutive characters\n");
    printf("The current size of the string is: %d\n", strlen(corners));
  }
  else{
    theCube[C1].w = corners[0];
    theCube[C1].o = corners[1];
    theCube[C1].g = corners[2];
    theCube[C2].w = corners[3];
    theCube[C2].b = corners[4];
    theCube[C2].o = corners[5];
    theCube[C3].r = corners[6];
    theCube[C3].w = corners[7];
    theCube[C3].g = corners[8];
    theCube[C4].r = corners[9];
    theCube[C4].w = corners[10];
    theCube[C4].b = corners[11];
    theCube[C5].r = corners[12];
    theCube[C5].b = corners[13];
    theCube[C5].y = corners[14];
    theCube[C6].b = corners[15];
    theCube[C6].o = corners[16];
    theCube[C6].y = corners[17];
    theCube[C7].r = corners[18];
    theCube[C7].y = corners[19];
    theCube[C7].g = corners[20];
    theCube[C8].o = corners[21];
    theCube[C8].y = corners[22];
    theCube[C8].g = corners[23];
  }
  //printCrossCube( theCube );
}


void setEdgesFromString(struct aCube * theCube, char edges[]){
  if( strlen(edges) != 24 ){
    printf("Please enter an array with 24 consecutive characters\n");
    printf("The current size of the string is: %d\n", strlen(edges));
  }
  else{
    theCube[ E9].w = edges[0];
    theCube[ E9].o = edges[1];
    theCube[E10].w = edges[2];
    theCube[E10].b = edges[3];
    theCube[E11].r = edges[4];
    theCube[E11].w = edges[5];
    theCube[E12].w = edges[6];
    theCube[E12].g = edges[7];
    theCube[E13].b = edges[8];
    theCube[E13].y = edges[9];
    theCube[E14].y = edges[10];
    theCube[E14].o = edges[11];
    theCube[E15].y = edges[12];
    theCube[E15].g = edges[13];
    theCube[E16].r = edges[14];
    theCube[E16].y = edges[15];
    theCube[E17].r = edges[16];
    theCube[E17].g = edges[17];
    theCube[E18].r = edges[18];
    theCube[E18].b = edges[19];
    theCube[E19].b = edges[20];
    theCube[E19].o = edges[21];
    theCube[E20].o = edges[22];
    theCube[E20].g = edges[23];
    //printCrossCube( theCube );
  }  
}


void setCubeFromStrings(struct aCube * theCube, char corners[], char edges[]){
  if( strlen(corners) != 24 || strlen(edges) != 24){
    printf("Please enter 24 character arrays for both corners and edges.\n");
    printf("The current size of the corners string is: %d\n", strlen(corners));
    printf("The current size of the edges string is: %d\n", strlen(edges));
  }
  else{
    theCube[C1].w = corners[0];
    theCube[C1].o = corners[1];
    theCube[C1].g = corners[2];
    theCube[C2].w = corners[3];
    theCube[C2].b = corners[4];
    theCube[C2].o = corners[5];
    theCube[C3].r = corners[6];
    theCube[C3].w = corners[7];
    theCube[C3].g = corners[8];
    theCube[C4].r = corners[9];
    theCube[C4].w = corners[10];
    theCube[C4].b = corners[11];
    theCube[C5].r = corners[12];
    theCube[C5].b = corners[13];
    theCube[C5].y = corners[14];
    theCube[C6].b = corners[15];
    theCube[C6].o = corners[16];
    theCube[C6].y = corners[17];
    theCube[C7].r = corners[18];
    theCube[C7].y = corners[19];
    theCube[C7].g = corners[20];
    theCube[C8].o = corners[21];
    theCube[C8].y = corners[22];
    theCube[C8].g = corners[23];

    theCube[E9].w = edges[0];
    theCube[E9].o = edges[1];
    theCube[E10].w = edges[2];
    theCube[E10].b = edges[3];
    theCube[E11].r = edges[4];
    theCube[E11].w = edges[5];
    theCube[E12].w = edges[6];
    theCube[E12].g = edges[7];
    theCube[E13].b = edges[8];
    theCube[E13].y = edges[9];
    theCube[E14].y = edges[10];
    theCube[E14].o = edges[11];
    theCube[E15].y = edges[12];
    theCube[E15].g = edges[13];
    theCube[E16].r = edges[14];
    theCube[E16].y = edges[15];
    theCube[E17].r = edges[16];
    theCube[E17].g = edges[17];
    theCube[E18].r = edges[18];
    theCube[E18].b = edges[19];
    theCube[E19].b = edges[20];
    theCube[E19].o = edges[21];
    theCube[E20].o = edges[22];
    theCube[E20].g = edges[23];
  }
}


void setCubeFromString(struct aCube * theCube, char string[]){
  if( strlen(string) != 48 ){
    printf("Please enter an array with 48 consecutive characters\n");
    printf("The first 24 chars should be the corners, the next 24 the edges\n");
    printf("The current size of the string is: %d\n", strlen(string));
  }
  else{
    theCube[C1].w = string[0];
    theCube[C1].o = string[1];
    theCube[C1].g = string[2];
    theCube[C2].w = string[3];
    theCube[C2].b = string[4];
    theCube[C2].o = string[5];
    theCube[C3].r = string[6];
    theCube[C3].w = string[7];
    theCube[C3].g = string[8];
    theCube[C4].r = string[9];
    theCube[C4].w = string[10];
    theCube[C4].b = string[11];
    theCube[C5].r = string[12];
    theCube[C5].b = string[13];
    theCube[C5].y = string[14];
    theCube[C6].b = string[15];
    theCube[C6].o = string[16];
    theCube[C6].y = string[17];
    theCube[C7].r = string[18];
    theCube[C7].y = string[19];
    theCube[C7].g = string[20];
    theCube[C8].o = string[21];
    theCube[C8].y = string[22];
    theCube[C8].g = string[23];
    theCube[E9].w = string[24];
    theCube[E9].o = string[25];
    theCube[E10].w = string[26];
    theCube[E10].b = string[27];
    theCube[E11].r = string[28];
    theCube[E11].w = string[29];
    theCube[E12].w = string[30];
    theCube[E12].g = string[31];
    theCube[E13].b = string[32];
    theCube[E13].y = string[33];
    theCube[E14].y = string[34];
    theCube[E14].o = string[35];
    theCube[E15].y = string[36];
    theCube[E15].g = string[37];
    theCube[E16].r = string[38];
    theCube[E16].y = string[39];
    theCube[E17].r = string[40];
    theCube[E17].g = string[41];
    theCube[E18].r = string[42];
    theCube[E18].b = string[43];
    theCube[E19].b = string[44];
    theCube[E19].o = string[45];
    theCube[E20].o = string[46];
    theCube[E20].g = string[47];
  }
  //printCrossCube( theCube );                                                                
}


void generateCorners( struct aCube * theCube, FILE* cornerFile, short currentDepth,//
 char input01, char input02, char input03, char input04, char input05, char input06,//
 char input07, char input08, char input09, char input10, char input11, char input12,//
 char input13, char input14, char input15, char input16, char input17, char input18,//
 char input19, char input20, char input21, char input22, char input23, char input24 ) {

  theCube[C1].w = input01;
  theCube[C1].o = input02;
  theCube[C1].g = input03;
  theCube[C2].w = input04;
  theCube[C2].b = input05;
  theCube[C2].o = input06;
  theCube[C3].r = input07;
  theCube[C3].w = input08;
  theCube[C3].g = input09;
  theCube[C4].r = input10;
  theCube[C4].w = input11;
  theCube[C4].b = input12;
  theCube[C5].r = input13;
  theCube[C5].b = input14;
  theCube[C5].y = input15;
  theCube[C6].b = input16;
  theCube[C6].o = input17;
  theCube[C6].y = input18;
  theCube[C7].r = input19;
  theCube[C7].y = input20;
  theCube[C7].g = input21;
  theCube[C8].o = input22;
  theCube[C8].y = input23;
  theCube[C8].g = input24;

  if( MAXDEPTH == currentDepth ) return;
  else{
    char face[6] = { 'r', 'w', 'b', 'o', 'y', 'g' };
    int i, j;
    for( i=0; i<=5; i++) {
      for( j=1; j<=3; j++) {
        rotate( theCube, face[i], j);
        saveCornerCubie( theCube, cornerFile, currentDepth+1);
        generateCorners( theCube, cornerFile, currentDepth+1, PASSCORNERS);
      }
    }
  }
}


void generateEdges( struct aCube * theCube, FILE* edgeFile, short currentDepth,//
 char input01, char input02, char input03, char input04, char input05, char input06,//
 char input07, char input08, char input09, char input10, char input11, char input12,//
 char input13, char input14, char input15, char input16, char input17, char input18,//
 char input19, char input20, char input21, char input22, char input23, char input24 ) {

  theCube[E9].w  = input01;
  theCube[E9].o  = input02;
  theCube[E10].w = input03;
  theCube[E10].b = input04;
  theCube[E11].r = input05;
  theCube[E11].w = input06;
  theCube[E12].w = input07;
  theCube[E12].g = input08;
  theCube[E13].b = input09;
  theCube[E13].y = input10;
  theCube[E14].y = input11;
  theCube[E14].o = input12;
  theCube[E15].y = input13;
  theCube[E15].g = input14;
  theCube[E16].r = input15;
  theCube[E16].y = input16;
  theCube[E17].r = input17;
  theCube[E17].g = input18;
  theCube[E18].r = input19;
  theCube[E18].b = input20;
  theCube[E19].b = input21;
  theCube[E19].o = input22;
  theCube[E20].o = input23;
  theCube[E20].g = input24;

  if( MAXDEPTH == currentDepth ) return;
  else{
    char face[6] = { 'r', 'w', 'b', 'o', 'y', 'g' };
    int i, j;
    for( i=0; i<=5; i++) {
      for( j=1; j<=3; j++) {
        rotate( theCube, face[i], j);
        saveEdgeCubie( theCube, edgeFile, currentDepth+1);
        generateEdges( theCube, edgeFile, currentDepth+1, PASSEDGES);
      }
    }
  }  
}


void setCorners( struct aCube * cube, char input01, char input02, char input03, char input04,//
          char input05, char input06, char input07, char input08, char input09, char input10,//
          char input11, char input12, char input13, char input14, char input15, char input16,//
          char input17, char input18, char input19, char input20, char input21, char input22,//
          char input23, char input24 ) {

  cube[C1].w = input01;
  cube[C1].o = input02;
  cube[C1].g = input03;
  cube[C2].w = input04;
  cube[C2].b = input05;
  cube[C2].o = input06;
  cube[C3].r = input07;
  cube[C3].w = input08;
  cube[C3].g = input09;
  cube[C4].r = input10;
  cube[C4].w = input11;
  cube[C4].b = input12;
  cube[C5].r = input13;
  cube[C5].b = input14;
  cube[C5].y = input15;
  cube[C6].b = input16;
  cube[C6].o = input17;
  cube[C6].y = input18;
  cube[C7].r = input19;
  cube[C7].y = input20;
  cube[C7].g = input21;
  cube[C8].o = input22;
  cube[C8].y = input23;
  cube[C8].g = input24;
}


void setEdges( struct aCube * cube, char input01, char input02, char input03, char input04,//
        char input05, char input06, char input07, char input08, char input09, char input10,//
        char input11, char input12, char input13, char input14, char input15, char input16,//
        char input17, char input18, char input19, char input20, char input21, char input22,//
        char input23, char input24 ) { 

  cube[ E9].w = input01;
  cube[ E9].o = input02;
  cube[E10].w = input03;
  cube[E10].b = input04;
  cube[E11].r = input05;
  cube[E11].w = input06;
  cube[E12].w = input07;
  cube[E12].g = input08;
  cube[E13].b = input09;
  cube[E13].y = input10;
  cube[E14].y = input11;
  cube[E14].o = input12;
  cube[E15].y = input13;
  cube[E15].g = input14;
  cube[E16].r = input15;
  cube[E16].y = input16;
  cube[E17].r = input17;
  cube[E17].g = input18;
  cube[E18].r = input19;
  cube[E18].b = input20;
  cube[E19].b = input21;
  cube[E19].o = input22;
  cube[E20].o = input23;
  cube[E20].g = input24;
}


void scramble( struct aCube * cube, short n ) {
  srand( (unsigned int)time( NULL ) );
  
  short iter = 0;
  for(iter = 0; iter<n; iter++) {
    short randFace = rand() % 6;
    short randTurn = rand() % 3;
    char face[6] = { 'r', 'w', 'b', 'o', 'y', 'g' };
    int turn[3] = { 1, 2, 3 };
    rotate(cube, face[ randFace ], turn[ randTurn ]);
    printf("\n\nface:%2c rotate:%2d\n\n", face[ randFace ], turn[ randTurn ]); 
  }
}


void copyCube( struct aCube * newCube, struct aCube * oldCube) {

  newCube[C1].w = oldCube[C1].w;
  newCube[C1].o = oldCube[C1].o;
  newCube[C1].g = oldCube[C1].g;
  newCube[C2].w = oldCube[C2].w;
  newCube[C2].b = oldCube[C2].b;
  newCube[C2].o = oldCube[C2].o;
  newCube[C3].r = oldCube[C3].r;
  newCube[C3].w = oldCube[C3].w;
  newCube[C3].g = oldCube[C3].g;
  newCube[C4].r = oldCube[C4].r;
  newCube[C4].w = oldCube[C4].w;
  newCube[C4].b = oldCube[C4].b;
  newCube[C5].r = oldCube[C5].r;
  newCube[C5].b = oldCube[C5].b;
  newCube[C5].y = oldCube[C5].y;
  newCube[C6].b = oldCube[C6].b;
  newCube[C6].o = oldCube[C6].o;
  newCube[C6].y = oldCube[C6].y;
  newCube[C7].r = oldCube[C7].r;
  newCube[C7].y = oldCube[C7].y;
  newCube[C7].g = oldCube[C7].g;
  newCube[C8].o = oldCube[C8].o;
  newCube[C8].y = oldCube[C8].y;
  newCube[C8].g = oldCube[C8].g;

  newCube[ E9].w = oldCube[ E9].w;
  newCube[ E9].o = oldCube[ E9].o;
  newCube[E10].w = oldCube[E10].w;
  newCube[E10].b = oldCube[E10].b;
  newCube[E11].r = oldCube[E11].r;
  newCube[E11].w = oldCube[E11].w;
  newCube[E12].w = oldCube[E12].w;
  newCube[E12].g = oldCube[E12].g;
  newCube[E13].b = oldCube[E13].b;
  newCube[E13].y = oldCube[E13].y;
  newCube[E14].y = oldCube[E14].y;
  newCube[E14].o = oldCube[E14].o;
  newCube[E15].y = oldCube[E15].y;
  newCube[E15].g = oldCube[E15].g;
  newCube[E16].r = oldCube[E16].r;
  newCube[E16].y = oldCube[E16].y;
  newCube[E17].r = oldCube[E17].r;
  newCube[E17].g = oldCube[E17].g;
  newCube[E18].r = oldCube[E18].r;
  newCube[E18].b = oldCube[E18].b;
  newCube[E19].b = oldCube[E19].b;
  newCube[E19].o = oldCube[E19].o;
  newCube[E20].o = oldCube[E20].o;
  newCube[E20].g = oldCube[E20].g;
}


void resetCube( struct aCube * theCube) {
  struct aCube goalState[20] = {
    { 'Z', 'W', 'Z', 'O', 'Z', 'G'},
    { 'Z', 'W', 'B', 'O', 'Z', 'Z'},
    { 'R', 'W', 'Z', 'Z', 'Z', 'G'},
    { 'R', 'W', 'B', 'Z', 'Z', 'Z'},
    { 'R', 'Z', 'B', 'Z', 'Y', 'Z'},
    { 'Z', 'Z', 'B', 'O', 'Y', 'Z'},
    { 'R', 'Z', 'Z', 'Z', 'Y', 'G'},
    { 'Z', 'Z', 'Z', 'O', 'Y', 'G'},
    { 'Z', 'W', 'Z', 'O', 'Z', 'Z'},
    { 'Z', 'W', 'B', 'Z', 'Z', 'Z'},
    { 'R', 'W', 'Z', 'Z', 'Z', 'Z'},
    { 'Z', 'W', 'Z', 'Z', 'Z', 'G'},
    { 'Z', 'Z', 'B', 'Z', 'Y', 'Z'},
    { 'Z', 'Z', 'Z', 'O', 'Y', 'Z'},
    { 'Z', 'Z', 'Z', 'Z', 'Y', 'G'},
    { 'R', 'Z', 'Z', 'Z', 'Y', 'Z'},
    { 'R', 'Z', 'Z', 'Z', 'Z', 'G'},
    { 'R', 'Z', 'B', 'Z', 'Z', 'Z'},
    { 'Z', 'Z', 'B', 'O', 'Z', 'Z'},
    { 'Z', 'Z', 'Z', 'O', 'Z', 'G'}
  };

    theCube[C1].w = goalState[C1].w;
    theCube[C1].o = goalState[C1].o;
    theCube[C1].g = goalState[C1].g;
    theCube[C2].w = goalState[C2].w;
    theCube[C2].b = goalState[C2].b;
    theCube[C2].o = goalState[C2].o;
    theCube[C3].r = goalState[C3].r;
    theCube[C3].w = goalState[C3].w;
    theCube[C3].g = goalState[C3].g;
    theCube[C4].r = goalState[C4].r;
    theCube[C4].w = goalState[C4].w;
    theCube[C4].b = goalState[C4].b;
    theCube[C5].r = goalState[C5].r;
    theCube[C5].b = goalState[C5].b;
    theCube[C5].y = goalState[C5].y;
    theCube[C6].b = goalState[C6].b;
    theCube[C6].o = goalState[C6].o;
    theCube[C6].y = goalState[C6].y;
    theCube[C7].r = goalState[C7].r;
    theCube[C7].y = goalState[C7].y;
    theCube[C7].g = goalState[C7].g;
    theCube[C8].o = goalState[C8].o;
    theCube[C8].y = goalState[C8].y;
    theCube[C8].g = goalState[C8].g;

    theCube[ E9].w = goalState[ E9].w;
    theCube[ E9].o = goalState[ E9].o;
    theCube[E10].w = goalState[E10].w;
    theCube[E10].b = goalState[E10].b;
    theCube[E11].r = goalState[E11].r;
    theCube[E11].w = goalState[E11].w;
    theCube[E12].w = goalState[E12].w;
    theCube[E12].g = goalState[E12].g;
    theCube[E13].b = goalState[E13].b;
    theCube[E13].y = goalState[E13].y;
    theCube[E14].y = goalState[E14].y;
    theCube[E14].o = goalState[E14].o;
    theCube[E15].y = goalState[E15].y;
    theCube[E15].g = goalState[E15].g;
    theCube[E16].r = goalState[E16].r;
    theCube[E16].y = goalState[E16].y;
    theCube[E17].r = goalState[E17].r;
    theCube[E17].g = goalState[E17].g;
    theCube[E18].r = goalState[E18].r;
    theCube[E18].b = goalState[E18].b;
    theCube[E19].b = goalState[E19].b;
    theCube[E19].o = goalState[E19].o;
    theCube[E20].o = goalState[E20].o;
    theCube[E20].g = goalState[E20].g;
}

void allRotations() {
  int i,j;
  char face[6] = { 'r', 'w', 'b', 'o', 'y', 'g' };
  for( i=0; i<=5; i++) {
      for( j=1; j<=3; j++) {
	  struct aCube cube[20] = {
    { 'Z', 'W', 'Z', 'O', 'Z', 'G'},
    { 'Z', 'W', 'B', 'O', 'Z', 'Z'},
    { 'R', 'W', 'Z', 'Z', 'Z', 'G'},
    { 'R', 'W', 'B', 'Z', 'Z', 'Z'},
    { 'R', 'Z', 'B', 'Z', 'Y', 'Z'},
    { 'Z', 'Z', 'B', 'O', 'Y', 'Z'},
    { 'R', 'Z', 'Z', 'Z', 'Y', 'G'},
    { 'Z', 'Z', 'Z', 'O', 'Y', 'G'},
    { 'Z', 'W', 'Z', 'O', 'Z', 'Z'},
    { 'Z', 'W', 'B', 'Z', 'Z', 'Z'},
    { 'R', 'W', 'Z', 'Z', 'Z', 'Z'},
    { 'Z', 'W', 'Z', 'Z', 'Z', 'G'},
    { 'Z', 'Z', 'B', 'Z', 'Y', 'Z'},
    { 'Z', 'Z', 'Z', 'O', 'Y', 'Z'},
    { 'Z', 'Z', 'Z', 'Z', 'Y', 'G'},
    { 'R', 'Z', 'Z', 'Z', 'Y', 'Z'},
    { 'R', 'Z', 'Z', 'Z', 'Z', 'G'},
    { 'R', 'Z', 'B', 'Z', 'Z', 'Z'},
    { 'Z', 'Z', 'B', 'O', 'Z', 'Z'},
    { 'Z', 'Z', 'Z', 'O', 'Z', 'G'}
	  };
          printf("\n\nface:%2c rotate:%2d\n\n", face[i], j);
          rotate( cube, face[i], j);
          printCrossCube( cube);
          }
  }
}


/*******************************************************************/
/***************** Print / Save State Funcitions *******************/
/*******************************************************************/

void saveCornerCubie( struct aCube * cube, FILE* filename, short distToGoal) {
  fprintf( filename, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%d\n",//
          cube[C1].w, cube[C1].o, cube[C1].g, cube[C2].w, cube[C2].b, cube[C2].o,//
          cube[C3].r, cube[C3].w, cube[C3].g, cube[C4].r, cube[C4].w, cube[C4].b,//
          cube[C5].r, cube[C5].b, cube[C5].y, cube[C6].b, cube[C6].o, cube[C6].y,//
          cube[C7].r, cube[C7].y, cube[C7].g, cube[C8].o, cube[C8].y, cube[C8].g, distToGoal);
}

void saveEdgeCubie( struct aCube * cube, FILE* filename, short distToGoal) {
  fprintf( filename, "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%d\n",//
          cube[E9].w,  cube[E9].o,  cube[E10].w, cube[E10].b, cube[E11].r, cube[E11].w,//
          cube[E12].w, cube[E12].g, cube[E13].b, cube[E13].y, cube[E14].y, cube[E14].o,//
          cube[E15].y, cube[E15].g, cube[E16].r, cube[E16].y, cube[E17].r, cube[E17].g,//
          cube[E18].r, cube[E18].b, cube[E19].b, cube[E19].o, cube[E20].o, cube[E20].g, distToGoal);
}

void printStepCube(struct aCube * cube) {
  printf("\n");
  printf("%c  %c  %c\n", cube[C1].w, cube[E9].w, cube[C2].w );
  printf("%c  W  %c \n", cube[E12].w, cube[E10].w );
  printf("%c  %c  %c \n\n", 
	  cube[C3].w, cube[E11].w, cube[C4].w );

  printf("%c  %c  %c    %c  %c  %c\n", 
	  cube[C3].r, cube[E11].r, cube[C4].r,  
	  cube[C4].b, cube[E10].b, cube[C2].b );
  printf("%c  R  %c    %c  B  %c\n", 
	  cube[E17].r, cube[E18].r, 
	  cube[E18].b, cube[E19].b );
  printf("%c  %c  %c    %c  %c  %c\n\n", 
	  cube[C7].r, cube[E16].r, cube[C5].r, 
	  cube[C5].b, cube[E13].b, cube[C6].b );

  printf("\t   %c  %c  %c    %c  %c  %c\n",  
	  cube[C5].y,  cube[E13].y, cube[C6].y,  
	  cube[C6].o,  cube[E19].o, cube[C2].o );
  printf("\t   %c  Y  %c    %c  O  %c\n", 
	  cube[E16].y, cube[E14].y, 
	  cube[E14].o,  cube[E9].o );
  printf("\t   %c  %c  %c    %c  %c  %c\n\n", 
	  cube[C7].y, cube[E15].y, cube[C8].y, 
	  cube[C8].o, cube[E20].o, cube[C1].o );

  printf("\t\t      %c  %c  %c\n",  
	  cube[C8].g, cube[E20].g, cube[C1].g );
  printf("\t\t      %c  G  %c\n", 
	  cube[E15].g, cube[E12].g );
  printf("\t\t      %c  %c  %c\n",  
	  cube[C7].g, cube[E17].g, cube[C3].g );
  printf("\n");
}


void printCrossCube(struct aCube * cube) {
  printf("\n");
  printf("\t   %c  %c  %c\t       %c  %c  %c\n",
          cube[C8].o,  cube[E14].o, cube[C6].o,
          cube[C2].o,  cube[E9].o, cube[C1].o );
  printf("\t   %c  O  %c\t       %c  O  %c\n",
          cube[E20].o, cube[E19].o,
          cube[E19].o, cube[E20].o  );
  printf("\t   %c  %c  %c\t       %c  %c  %c\n",
          cube[C1].o,  cube[E9].o, cube[C2].o,
          cube[C6].o, cube[E14].o, cube[C8].o );
  printf("\n");
  printf(" %c  %c  %c   %c  %c  %c   %c  %c  %c   %c  %c  %c   %c  %c  %c\n",
          cube[C8].g,  cube[E20].g,  cube[C1].g,
          cube[C1].w,   cube[E9].w,  cube[C2].w,
          cube[C2].b,  cube[E19].b,  cube[C6].b,
          cube[C6].y,  cube[E14].y,  cube[C8].y,
          cube[C8].g,  cube[E20].g,  cube[C1].g );
  printf(" %c  G  %c   %c  W  %c   %c  B  %c   %c  Y  %c   %c  G  %c\n",
          cube[E15].g,  cube[E12].g,
          cube[E12].w,  cube[E10].w,
          cube[E10].b,  cube[E13].b,
          cube[E13].y,  cube[E15].y,
          cube[E15].g,  cube[E12].g );
  printf(" %c  %c  %c   %c  %c  %c   %c  %c  %c   %c  %c  %c   %c  %c  %c\n",
          cube[C7].g,  cube[E17].g,  cube[C3].g,
          cube[C3].w,  cube[E11].w,  cube[C4].w,
          cube[C4].b,  cube[E18].b,  cube[C5].b,
          cube[C5].y,  cube[E16].y,  cube[C7].y,
          cube[C7].g,  cube[E17].g,  cube[C3].g );
  printf("\n");
  printf("\t   %c  %c  %c\t       %c  %c  %c\n",
          cube[C3].r, cube[E11].r, cube[C4].r,
          cube[C5].r, cube[E16].r, cube[C7].r );
  printf("\t   %c  R  %c\t       %c  R  %c\n",
          cube[E17].r, cube[E18].r,
          cube[E18].r, cube[E17].r );
  printf("\t   %c  %c  %c\t       %c  %c  %c\n",
          cube[C7].r, cube[E16].r, cube[C5].r,
          cube[C4].r, cube[E11].r, cube[C3].r  );
  printf("\n");
}


/*******************************************************************/
/********************* Face Rotation Funcitions ********************/
/*******************************************************************/

void r1c(struct aCube * cube) {
  char temp = cube[C3].r;
  cube[C3].r = cube[C7].r;
  cube[C7].r = cube[C5].r;
  cube[C5].r = cube[C4].r;
  cube[C4].r = temp;

  temp = cube[C3].w;
  cube[C3].w = cube[C7].g;
  cube[C7].g = cube[C5].y;
  cube[C5].y = cube[C4].b;
  cube[C4].b = temp;

  temp = cube[C3].g;
  cube[C3].g = cube[C7].y;
  cube[C7].y = cube[C5].b;
  cube[C5].b = cube[C4].w;
  cube[C4].w = temp;
  
}

void r1e(struct aCube * cube) {
  char temp = cube[E11].r;
  cube[E11].r = cube[E17].r;
  cube[E17].r = cube[E16].r;
  cube[E16].r = cube[E18].r;
  cube[E18].r = temp;

  temp = cube[E11].w;
  cube[E11].w = cube[E17].g;
  cube[E17].g = cube[E16].y;
  cube[E16].y = cube[E18].b;
  cube[E18].b = temp;
}

void r2c(struct aCube * cube) {
  char temp = cube[C3].r;
  cube[C3].r = cube[C5].r;
  cube[C5].r = temp;

  temp = cube[C4].r;
  cube[C4].r = cube[C7].r;
  cube[C7].r = temp;

  temp = cube[C3].w;
  cube[C3].w = cube[C5].y;
  cube[C5].y = temp;

  temp = cube[C3].g;
  cube[C3].g = cube[C5].b; 
  cube[C5].b = temp;

  temp = cube[C4].w;
  cube[C4].w = cube[C7].y;
  cube[C7].y = temp;

  temp = cube[C4].b;
  cube[C4].b = cube[C7].g;
  cube[C7].g = temp;
}

void r2e(struct aCube * cube) {
  char temp = cube[E11].r;
  cube[E11].r = cube[E16].r;
  cube[E16].r = temp;

  temp = cube[E17].r;
  cube[E17].r = cube[E18].r;
  cube[E18].r = temp;

  temp = cube[E11].w;
  cube[E11].w = cube[E16].y;
  cube[E16].y = temp;

  temp = cube[E17].g;
  cube[E17].g = cube[E18].b;
  cube[E18].b = temp;
}

void r3c(struct aCube * cube) {
  char temp = cube[C3].r;
  cube[C3].r = cube[C4].r;
  cube[C4].r = cube[C5].r;
  cube[C5].r = cube[C7].r;
  cube[C7].r = temp;

  temp = cube[C3].w;
  cube[C3].w = cube[C4].b;
  cube[C4].b = cube[C5].y;
  cube[C5].y = cube[C7].g;
  cube[C7].g = temp;

  temp = cube[C3].g;
  cube[C3].g = cube[C4].w;
  cube[C4].w = cube[C5].b;
  cube[C5].b = cube[C7].y;
  cube[C7].y = temp;
}

void r3e(struct aCube * cube) {
  char temp = cube[E11].r;
  cube[E11].r = cube[E18].r;
  cube[E18].r = cube[E16].r;
  cube[E16].r = cube[E17].r;
  cube[E17].r = temp;

  temp = cube[E11].w;
  cube[E11].w = cube[E18].b;
  cube[E18].b = cube[E16].y;
  cube[E16].y = cube[E17].g;
  cube[E17].g = temp;
}



void w1c(struct aCube * cube) {
  char temp = cube[C1].o;
  cube[C1].o = cube[C3].g;
  cube[C3].g = cube[C4].r;
  cube[C4].r = cube[C2].b;
  cube[C2].b = temp;

  temp = cube[C1].g;
  cube[C1].g = cube[C3].r;
  cube[C3].r = cube[C4].b;
  cube[C4].b = cube[C2].o;
  cube[C2].o = temp;

  temp = cube[C1].w;
  cube[C1].w = cube[C3].w;
  cube[C3].w = cube[C4].w;
  cube[C4].w = cube[C2].w;
  cube[C2].w = temp;
}

void w1e(struct aCube * cube) {
  char temp = cube[E9].o;
  cube[E9].o = cube[E12].g;
  cube[E12].g = cube[E11].r;
  cube[E11].r = cube[E10].b;
  cube[E10].b = temp;

  temp = cube[E9].w;
  cube[E9].w = cube[E12].w;
  cube[E12].w = cube[E11].w;
  cube[E11].w = cube[E10].w;
  cube[E10].w = temp;
}

void w2c(struct aCube * cube) {
  char temp = cube[C1].o;
  cube[C1].o = cube[C4].r;
  cube[C4].r = temp;
  temp = cube[C1].g;
  cube[C1].g = cube[C4].b;
  cube[C4].b = temp;

  temp = cube[C2].b;
  cube[C2].b = cube[C3].g;
  cube[C3].g = temp;
  temp = cube[C2].o;
  cube[C2].o = cube[C3].r;
  cube[C3].r = temp;

  temp = cube[C1].w;
  cube[C1].w = cube[C4].w;
  cube[C4].w = temp;
  temp = cube[C2].w;
  cube[C2].w = cube[C3].w;
  cube[C3].w = temp;
}

void w2e(struct aCube * cube) {
  char temp = cube[E9].o;
  cube[E9].o = cube[E11].r;
  cube[E11].r = temp;
  temp = cube[E12].g; 
  cube[E12].g = cube[E10].b;
  cube[E10].b = temp;
  
  temp = cube[E9].w;
  cube[E9].w = cube[E11].w;
  cube[E11].w = temp;
  temp = cube[E12].w;
  cube[E12].w = cube[E10].w;
  cube[E10].w = temp;
}

void w3c(struct aCube * cube) {
  char temp = cube[C1].o;
  cube[C1].o = cube[C2].b;
  cube[C2].b = cube[C4].r;
  cube[C4].r = cube[C3].g;
  cube[C3].g = temp; 

  temp = cube[C1].g;
  cube[C1].g = cube[C2].o;
  cube[C2].o = cube[C4].b;
  cube[C4].b = cube[C3].r;
  cube[C3].r = temp;

  temp = cube[C1].w;
  cube[C1].w = cube[C2].w;
  cube[C2].w = cube[C4].w;
  cube[C4].w = cube[C3].w;
  cube[C3].w = temp;
}

void w3e(struct aCube * cube) {
  char temp  = cube[E9].o;
  cube[E9].o  = cube[E10].b;
  cube[E10].b = cube[E11].r;
  cube[E11].r = cube[E12].g;
  cube[E12].g = temp;

  temp = cube[E9].w;
  cube[E9].w  = cube[E10].w;
  cube[E10].w = cube[E11].w;
  cube[E11].w = cube[E12].w;
  cube[E12].w = temp;
}


void b1c(struct aCube * cube) {
  char temp = cube[C4].b;
  cube[C4].b = cube[C5].b;
  cube[C5].b = cube[C6].b;
  cube[C6].b = cube[C2].b;
  cube[C2].b = temp;

  temp = cube[C4].w;
  cube[C4].w = cube[C5].r;
  cube[C5].r = cube[C6].y;
  cube[C6].y = cube[C2].o;
  cube[C2].o = temp;

  temp = cube[C4].r;
  cube[C4].r = cube[C5].y;
  cube[C5].y = cube[C6].o;
  cube[C6].o = cube[C2].w;
  cube[C2].w = temp;
}

void b1e(struct aCube * cube) {
  char temp = cube[E10].b;
  cube[E10].b = cube[E18].b;
  cube[E18].b = cube[E13].b;
  cube[E13].b = cube[E19].b;
  cube[E19].b = temp;
  
  temp = cube[E10].w;
  cube[E10].w = cube[E18].r;
  cube[E18].r = cube[E13].y;
  cube[E13].y = cube[E19].o;
  cube[E19].o = temp;
}

void b2c(struct aCube * cube) {
  char temp = cube[C4].b;
  cube[C4].b = cube[C6].b;
  cube[C6].b = temp;
  temp = cube[C2].b;
  cube[C2].b = cube[C5].b;
  cube[C5].b = temp;

  temp = cube[C4].w;
  cube[C4].w = cube[C6].y;
  cube[C6].y = temp;
  temp = cube[C4].r;
  cube[C4].r = cube[C6].o;
  cube[C6].o = temp;

  temp = cube[C2].w;
  cube[C2].w = cube[C5].y;
  cube[C5].y = temp;
  temp = cube[C2].o;
  cube[C2].o = cube[C5].r;
  cube[C5].r = temp;
}

void b2e(struct aCube * cube) {
  char temp = cube[E10].b;
  cube[E10].b = cube[E13].b;
  cube[E13].b = temp;
  temp = cube[E18].b;
  cube[E18].b = cube[E19].b;
  cube[E19].b = temp;

  temp = cube[E10].w;
  cube[E10].w = cube[E13].y;
  cube[E13].y = temp;
  temp = cube[E18].r;
  cube[E18].r = cube[E19].o;
  cube[E19].o = temp;
}

void b3c(struct aCube * cube) {
  char temp = cube[C4].b;
  cube[C4].b = cube[C2].b;
  cube[C2].b = cube[C6].b;
  cube[C6].b = cube[C5].b;
  cube[C5].b = temp;

  temp = cube[C4].w;
  cube[C4].w = cube[C2].o;
  cube[C2].o = cube[C6].y;
  cube[C6].y = cube[C5].r;
  cube[C5].r = temp;

  temp = cube[C4].r;
  cube[C4].r = cube[C2].w;
  cube[C2].w = cube[C6].o;
  cube[C6].o = cube[C5].y;
  cube[C5].y = temp;
}

void b3e(struct aCube * cube) {
  char temp = cube[E10].b;
  cube[E10].b = cube[E19].b;
  cube[E19].b = cube[E13].b;
  cube[E13].b = cube[E18].b;
  cube[E18].b = temp;

  temp = cube[E10].w;
  cube[E10].w = cube[E19].o;
  cube[E19].o = cube[E13].y;
  cube[E13].y = cube[E18].r;
  cube[E18].r = temp;
}



void o1c(struct aCube * cube) {
  char temp = cube[C6].o;
  cube[C6].o = cube[C8].o;
  cube[C8].o = cube[C1].o;
  cube[C1].o = cube[C2].o;
  cube[C2].o = temp;

  temp = cube[C6].b;
  cube[C6].b = cube[C8].y;
  cube[C8].y = cube[C1].g;
  cube[C1].g = cube[C2].w;
  cube[C2].w = temp;

  temp = cube[C6].y; 
  cube[C6].y = cube[C8].g;
  cube[C8].g = cube[C1].w;
  cube[C1].w = cube[C2].b;
  cube[C2].b = temp;
}

void o1e(struct aCube * cube) {
  char temp = cube[E19].o;
  cube[E19].o = cube[E14].o;
  cube[E14].o = cube[E20].o;
  cube[E20].o = cube[E9].o;
  cube[E9].o = temp;
  
  temp = cube[E19].b;
  cube[E19].b = cube[E14].y;
  cube[E14].y = cube[E20].g;
  cube[E20].g = cube[E9].w;
  cube[E9].w = temp;
}

void o2c(struct aCube * cube) {
  char temp = cube[C6].o;
  cube[C6].o = cube[C1].o;
  cube[C1].o = temp;

  temp = cube[C2].o;
  cube[C2].o = cube[C8].o;
  cube[C8].o = temp;

  temp = cube[C6].b;
  cube[C6].b = cube[C1].g;
  cube[C1].g = temp;

  temp = cube[C6].y;
  cube[C6].y = cube[C1].w;
  cube[C1].w = temp;

  temp = cube[C2].b;
  cube[C2].b = cube[C8].g;
  cube[C8].g = temp;

  temp = cube[C2].w;
  cube[C2].w = cube[C8].y;
  cube[C8].y = temp;
}

void o2e(struct aCube * cube) {
  char temp = cube[E19].o;
  cube[E19].o = cube[E20].o;
  cube[E20].o = temp;

  temp = cube[E14].o;
  cube[E14].o = cube[E9].o;
  cube[E9].o = temp;

  temp = cube[E19].b;
  cube[E19].b = cube[E20].g;
  cube[E20].g = temp;

  temp = cube[E14].y;
  cube[E14].y = cube[E9].w;
  cube[E9].w = temp;
}

void o3c(struct aCube * cube) {
  char temp = cube[C6].o;
  cube[C6].o = cube[C2].o;
  cube[C2].o = cube[C1].o;
  cube[C1].o = cube[C8].o;
  cube[C8].o = temp;

  temp = cube[C6].b;
  cube[C6].b = cube[C2].w;
  cube[C2].w = cube[C1].g; 
  cube[C1].g = cube[C8].y;
  cube[C8].y = temp;

  temp = cube[C6].y;
  cube[C6].y = cube[C2].b; 
  cube[C2].b = cube[C1].w;
  cube[C1].w = cube[C8].g;
  cube[C8].g = temp;
}

void o3e(struct aCube * cube) {
  char temp = cube[E19].o;
  cube[E19].o = cube[E9].o;
  cube[E9].o  = cube[E20].o;
  cube[E20].o = cube[E14].o;
  cube[E14].o = temp;

  temp = cube[E19].b;
  cube[E19].b = cube[E9].w;
  cube[E9].w  = cube[E20].g;
  cube[E20].g  = cube[E14].y;
  cube[E14].y =temp;
}


void y1c(struct aCube * cube) {
  char temp = cube[C8].y;
  cube[C8].y = cube[C6].y;
  cube[C6].y = cube[C5].y;
  cube[C5].y = cube[C7].y;
  cube[C7].y = temp;

  temp = cube[C8].o;
  cube[C8].o = cube[C6].b;
  cube[C6].b = cube[C5].r;
  cube[C5].r = cube[C7].g;
  cube[C7].g = temp;

  temp = cube[C8].g;
  cube[C8].g = cube[C6].o;
  cube[C6].o = cube[C5].b;
  cube[C5].b = cube[C7].r;
  cube[C7].r = temp;
}

void y1e(struct aCube * cube) {
  char temp = cube[E14].y;
  cube[E14].y = cube[E13].y;
  cube[E13].y = cube[E16].y;
  cube[E16].y = cube[E15].y;
  cube[E15].y = temp;

  temp = cube[E14].o;
  cube[E14].o = cube[E13].b;
  cube[E13].b = cube[E16].r;
  cube[E16].r = cube[E15].g;
  cube[E15].g = temp;
}

void y2c(struct aCube * cube) {
  char temp = cube[C6].y;
  cube[C6].y = cube[C7].y;
  cube[C7].y = temp;
  temp = cube[C5].y;
  cube[C5].y = cube[C8].y;
  cube[C8].y = temp;

  temp = cube[C6].o;
  cube[C6].o = cube[C7].r;
  cube[C7].r = temp;
  temp = cube[C5].b;
  cube[C5].b = cube[C8].g;
  cube[C8].g = temp;

  temp = cube[C6].b;
  cube[C6].b = cube[C7].g;
  cube[C7].g = temp;
  temp = cube[C5].r;
  cube[C5].r = cube[C8].o;
  cube[C8].o = temp;
}

void y2e(struct aCube * cube) {
  char temp = cube[E14].y;
  cube[E14].y = cube[E16].y;
  cube[E16].y = temp;
  temp = cube[E13].y;
  cube[E13].y = cube[E15].y;
  cube[E15].y = temp;

  temp = cube[E14].o;
  cube[E14].o = cube[E16].r;
  cube[E16].r = temp;
  temp = cube[E13].b;
  cube[E13].b = cube[E15].g;
  cube[E15].g = temp;
}

void y3c(struct aCube * cube) {
  char temp = cube[C8].y;
  cube[C8].y = cube[C7].y;
  cube[C7].y = cube[C5].y;
  cube[C5].y = cube[C6].y;
  cube[C6].y = temp;

  temp = cube[C8].o;
  cube[C8].o = cube[C7].g;
  cube[C7].g = cube[C5].r;
  cube[C5].r = cube[C6].b;
  cube[C6].b = temp;

  temp = cube[C8].g;
  cube[C8].g = cube[C7].r;
  cube[C7].r = cube[C5].b;
  cube[C5].b = cube[C6].o;
  cube[C6].o = temp;
}

void y3e(struct aCube * cube) {
  char temp = cube[E14].y;
  cube[E14].y = cube[E15].y;
  cube[E15].y = cube[E16].y;
  cube[E16].y = cube[E13].y;
  cube[E13].y = temp;

  temp = cube[E14].o;
  cube[E14].o = cube[E15].g;
  cube[E15].g = cube[E16].r;
  cube[E16].r = cube[E13].b;
  cube[E13].b = temp;
}



void g1c(struct aCube * cube) {
  char temp = cube[C8].g;
  cube[C8].g = cube[C7].g;
  cube[C7].g = cube[C3].g;
  cube[C3].g = cube[C1].g;
  cube[C1].g = temp;

  temp = cube[C8].y;
  cube[C8].y = cube[C7].r;
  cube[C7].r = cube[C3].w;
  cube[C3].w = cube[C1].o;
  cube[C1].o = temp;

  temp = cube[C8].o;
  cube[C8].o = cube[C7].y;
  cube[C7].y = cube[C3].r;
  cube[C3].r = cube[C1].w;
  cube[C1].w = temp;
}

void g1e(struct aCube * cube) {
  char temp = cube[E20].g;
  cube[E20].g = cube[E15].g;
  cube[E15].g = cube[E17].g;
  cube[E17].g = cube[E12].g;
  cube[E12].g = temp;

  temp = cube[E20].o;
  cube[E20].o = cube[E15].y;
  cube[E15].y = cube[E17].r;
  cube[E17].r = cube[E12].w;
  cube[E12].w = temp;
}

void g2c(struct aCube * cube) {
  char temp = cube[C1].g;
  cube[C1].g = cube[C7].g;
  cube[C7].g = temp;
  temp = cube[C3].g;
  cube[C3].g = cube[C8].g;
  cube[C8].g = temp;

  temp = cube[C1].o;
  cube[C1].o = cube[C7].r;
  cube[C7].r = temp;
  temp = cube[C3].w;
  cube[C3].w = cube[C8].y;
  cube[C8].y = temp;

  temp = cube[C1].w;
  cube[C1].w = cube[C7].y;
  cube[C7].y = temp;
  temp = cube[C3].r;
  cube[C3].r = cube[C8].o;
  cube[C8].o = temp;
}

void g2e(struct aCube * cube) {
  char temp = cube[E20].g;
  cube[E20].g = cube[E17].g;
  cube[E17].g = temp;
  temp = cube[E12].g;
  cube[E12].g = cube[E15].g;
  cube[E15].g = temp;

  temp = cube[E20].o;
  cube[E20].o = cube[E17].r;
  cube[E17].r = temp;
  temp = cube[E12].w;
  cube[E12].w = cube[E15].y;
  cube[E15].y = temp;
}

void g3c(struct aCube * cube) {
  char temp = cube[C1].g;
  cube[C1].g = cube[C3].g;
  cube[C3].g = cube[C7].g;
  cube[C7].g = cube[C8].g;
  cube[C8].g = temp;

  temp = cube[C1].o;
  cube[C1].o = cube[C3].w;
  cube[C3].w = cube[C7].r;
  cube[C7].r = cube[C8].y;
  cube[C8].y = temp;

  temp = cube[C1].w;
  cube[C1].w = cube[C3].r;
  cube[C3].r = cube[C7].y;
  cube[C7].y = cube[C8].o;
  cube[C8].o = temp;
}

void g3e(struct aCube * cube) {
  char temp = cube[E12].g;
  cube[E12].g = cube[E17].g;
  cube[E17].g = cube[E15].g;
  cube[E15].g = cube[E20].g;
  cube[E20].g = temp;

  temp = cube[E12].w;
  cube[E12].w = cube[E17].r;
  cube[E17].r = cube[E15].y;
  cube[E15].y = cube[E20].o;
  cube[E20].o = temp;
}



int rotate( struct aCube * cube, char f, int t) {
  switch (f){

  case 'r':
    switch (t){
    case 1:
      r1c( cube );
      r1e( cube );
      break;
    case 2: 
      r2c( cube );
      r2e( cube );
      break;
    case 3:
      r3c( cube );
      r3e( cube );
      break;
    }
  break;

  case 'w':
    switch (t){
    case 1: 
      w1c( cube );
      w1e( cube );
      break;
    case 2:
      w2c( cube );
      w2e( cube );
      break;
    case 3:
      w3c( cube );
      w3e( cube );
      break;
    }
    break;

  case 'b':
    switch (t){
    case 1: 
      b1c( cube );
      b1e( cube );
      break;
    case 2:
      b2c( cube );
      b2e( cube );
      break;
    case 3:
      b3c( cube );
      b3e( cube );
      break;
    }
    break;

  case 'o':
    switch (t){
    case 1: 
      o1c( cube );
      o1e( cube );
      break;
    case 2:
      o2c( cube );
      o2e( cube );
      break;
    case 3:
      o3c( cube );
      o3e( cube );
      break;
    }
    break;

  case 'y':
    switch (t){
    case 1:
      y1c( cube );
      y1e( cube );
      break;
    case 2:
      y2c( cube );
      y2e( cube );
      break;
    case 3:
      y3c( cube );
      y3e( cube );
      break;
    }
    break;

  case 'g':
    switch (t){
    case 1:
      g1c( cube );
      g1e( cube );
      break;
    case 2:
      g2c( cube );
      g2e( cube );
      break;
    case 3:
      g3c( cube );
      g3e( cube );
      break;
    }
    break;
  }
  return 0;
}

//Bottom of page.
